import path from 'node:path';
import fs from 'node:fs'
import electron from 'electron';
// 移除 @electron-toolkit/utils 导入，因为它在模块加载时会访问 electron.app 导致崩溃
// import { is } from '@electron-toolkit/utils'

// 安全的开发模式检测（不依赖 is.dev，避免模块加载时访问 electron.app）
const isDev = () => !electron.app.isPackaged;

// 配置管理 - 延迟获取路径，避免在模块加载时访问 electron.app
const getConfigFilePath = () => path.join(electron.app.getPath('userData'), 'config.json');
function loadConfig() {
  try {
    const data = fs.readFileSync(getConfigFilePath(), 'utf8');
    return JSON.parse(data);
  } catch (error: any) {
    if (error.code === 'ENOENT') {
      // 文件不存在，创建一个默认的配置文件
      const defaultConfig = { isTest: false };
      saveConfig(defaultConfig);
      return defaultConfig;
    } else {
      throw error;
    }
  }
}
function saveConfig(config: object) {
  const data = JSON.stringify(config, null, 2);
  fs.writeFileSync(getConfigFilePath(), data, 'utf8');
}


// 延迟获取扩展路径，避免在模块加载时访问 is.dev
const getExtPath = () => {
    return isDev() ?
        path.join(__dirname, '../../src-extension') :
        path.join(electron.app.getAppPath(), '..', 'app.asar.unpacked', 'src-extension');
};

// 缓存浏览器对象
var browser: any = null;
// 标记扩展是否已加载
var extensionLoaded = false;

/**
 * 初始化会话配置，确保登录状态持久化
 */
const initSession = (session: any) => {
    try {
        // 获取并确保会话目录存在
        const { app } = electron;
        const userDataPath = app.getPath('userData');
        const sessionPath = path.join(userDataPath, 'xiaohongshu-session');
        
        if (!fs.existsSync(sessionPath)) {
            fs.mkdirSync(sessionPath, { recursive: true });
            console.log(`[xhs-browser] Created session directory: ${sessionPath}`);
        }
        
        // 配置存储路径
        session.setStoragePath(sessionPath);
        
        // 关键设置：启用持久化cookies
        session.cookies.setPersistSessionCookies(true);
        
        // 设置cookies安全级别
        session.setCertificateVerifyProc((request: any, callback: Function) => {
            // 总是信任证书，确保连接正常
            callback(0); // 0 = 信任证书
        });
        
        // 配置会话User-Agent
        session.setUserAgent(session.getUserAgent() + ' XHS-MCP');
        
        // 配置请求包含凭证信息并记录日志
        session.webRequest.onBeforeSendHeaders((details: any, callback: Function) => {
            // 确保headers对象存在
            if (!details.requestHeaders) {
                details.requestHeaders = {};
            }
            
            // 设置真实的User-Agent
            details.requestHeaders['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' + ' XHS-MCP';
            
            // 确保Cookie头存在
            if (!details.requestHeaders['Cookie']) {
                details.requestHeaders['Cookie'] = '';
            }
            
            // 确保请求总是携带凭证
            details.requestHeaders['credentials'] = 'include';
            
            // 针对小红书域名的特殊处理
            if (details.url.includes('xiaohongshu.com')) {
                // 确保重要的请求头存在
                details.requestHeaders['Origin'] = 'https://www.xiaohongshu.com';
                details.requestHeaders['Referer'] = 'https://www.xiaohongshu.com/';
                details.requestHeaders['X-Requested-With'] = 'XMLHttpRequest';
            }
            
            callback({ cancel: false, requestHeaders: details.requestHeaders });
        });
        
        // 配置响应处理以确保cookie正确保存
        session.webRequest.onHeadersReceived((details: any, callback: Function) => {
            // 确保响应头对象存在
            if (!details.responseHeaders) {
                details.responseHeaders = {};
            }
            
            // 处理Cookie相关的响应头，确保正确保存
            if (details.responseHeaders['Set-Cookie']) {
                console.log(`[xhs-browser] Received cookies from ${details.url}: ${details.responseHeaders['Set-Cookie'].length} cookies`);
            }
            
            // 删除可能导致问题的响应头
            delete details.responseHeaders['Set-Cookie2'];
            
            // 允许跨域请求携带凭证
            details.responseHeaders['Access-Control-Allow-Credentials'] = ['true'];
            
            callback({ cancel: false, responseHeaders: details.responseHeaders });
        });
        
        // 设置权限处理器
        session.setPermissionRequestHandler((webContents: any, permission: string, callback: Function) => {
            // 记录权限请求
            console.log(`[xhs-browser] Permission requested: ${permission}`);
            // 允许所有权限请求，确保应用功能正常
            callback(true);
        });
        
        // 监听cookies变化，记录调试信息
        session.cookies.on('changed', (event: any, cookie: any, cause: any, removed: boolean) => {
            if (!removed) {
                console.log(`[xhs-browser] Cookie updated: ${cookie.name} for ${cookie.domain}`);
            }
        });
        
        // 立即尝试从文件系统加载cookies
        session.cookies.flushStore().then(() => {
            console.log('[xhs-browser] Cookies flushed to disk for persistence');
            
            // 打印当前存储的cookies数量，用于调试
            session.cookies.getAll({}).then(cookies => {
                console.log(`[xhs-browser] Currently stored cookies: ${cookies.length}`);
            }).catch(err => {
                console.error('[xhs-browser] Error getting cookies:', err);
            });
        }).catch(err => {
            console.error('[xhs-browser] Error flushing cookies to disk:', err);
        });
        
        console.log('[xhs-browser] Session initialized with enhanced persistent cookie support');
    } catch (error: any) {
        console.error('[xhs-browser] Failed to initialize session:', error.message);
    }
};

/**
 * 确保扩展已加载到共享 session
 */
const ensureExtensionLoaded = async () => {
    if (extensionLoaded) return;

    const { session } = electron;
    const sharedSession = session.fromPartition('persist:xiaohongshu');
    
    // 初始化会话配置
    initSession(sharedSession);

    try {
        await sharedSession.loadExtension(getExtPath());
        console.log('[xhs-browser] Extension loaded successfully');
        extensionLoaded = true;
    } catch (err: any) {
        // 扩展可能已经加载过了
        if (err.message?.includes('already loaded')) {
            console.log('[xhs-browser] Extension already loaded');
            extensionLoaded = true;
        } else {
            console.error('[xhs-browser] Failed to load extension:', err.message);
        }
    }
};

/**
 * 获取｜创建小红书浏览器
 * @returns BrowserWindow
 */
const getBrowser = () => {
    if (browser && browser.isEnabled()) return browser;
    const { BrowserWindow, session, app } = electron;

    // 确保用户数据目录存在
    const userDataPath = app.getPath('userData');
    const sessionPath = path.join(userDataPath, 'xiaohongshu-session');
    
    if (!fs.existsSync(sessionPath)) {
        fs.mkdirSync(sessionPath, { recursive: true });
        console.log(`[xhs-browser] Created session directory: ${sessionPath}`);
    }
    
    // 关键改进：使用明确的持久化会话分区，确保cookies持久化
    const partitionName = 'persist:xiaohongshu';
    const sharedSession = session.fromPartition(partitionName);
    
    // 初始化会话配置
    initSession(sharedSession);

    // 确保扩展加载（异步，不阻塞窗口创建）
    ensureExtensionLoaded();

    browser = new BrowserWindow({
        width: 1024,
        height: 768,
        show: false,
        autoHideMenuBar: true,
        webPreferences: {
            // 使用与主窗口 webview 相同的 session，确保登录状态共享
            session: sharedSession,
            // 确保网络请求可以正确携带cookies
            webSecurity: false,
            // 允许跨域资源共享
            allowRunningInsecureContent: true,
            // 启用上下文隔离以提高安全性
            contextIsolation: true
        }
    });
    browser.on('close', (event: any) => {
        event.preventDefault();
        // 隐藏窗口而不是关闭
        browser.hide();
    });
    console.log('[xhs-browser] path=>', path.join(__dirname));
    // 调试控制台（临时开启以诊断扩展问题）
    browser.webContents.openDevTools();

    // 在页面开始加载时就注入扩展代码（模拟 document_start）
    const extensionCode = fs.readFileSync(path.join(getExtPath(), 'content.js'), 'utf8');

    browser.webContents.on('did-start-loading', async () => {
        try {
            console.log('[xhs-browser] Page started loading, preparing to inject extension');
        } catch (err: any) {
            console.error('[xhs-browser] Error on did-start-loading:', err.message);
        }
    });

    // 在文档准备好时立即注入（尽可能早）
    browser.webContents.on('dom-ready', async () => {
        try {
            console.log('[xhs-browser] DOM ready, injecting extension code');

            // 包装扩展代码，捕获执行错误
            const wrappedCode = `
                try {
                    ${extensionCode}
                    console.log('[Extension] Code executed successfully');
                } catch (err) {
                    console.error('[Extension] Execution error:', err.message, err.stack);
                    throw err;
                }
            `;

            // 注入到页面的主世界（MAIN world）
            await browser.webContents.executeJavaScript(wrappedCode);
            console.log('[xhs-browser] Extension code injected');

            await sleep(1); // 等待代码执行

            // 检查 window 对象中的内容
            const windowKeys = await browser.webContents.executeJavaScript('Object.keys(window).filter(k => k.includes("Aicu") || k.includes("XHS")).join(",")');
            console.log('[xhs-browser] Window keys with Aicu/XHS:', windowKeys || 'none');

            const hasApi = await browser.webContents.executeJavaScript('typeof AicuXHSApi !== "undefined"');
            console.log('[xhs-browser] Extension API available:', hasApi);

            if (!hasApi) {
                console.warn('[xhs-browser] Extension API not available, checking console errors...');
                // 获取控制台错误
                const consoleErrors = await browser.webContents.executeJavaScript(`
                    window.__extensionErrors || 'No errors captured'
                `);
                console.log('[xhs-browser] Console errors:', consoleErrors);
            }
        } catch (err: any) {
            console.error('[xhs-browser] Failed to inject extension:', err.message, err.stack);
        }
    });

    // 页面加载完成后，再次检查
    browser.webContents.on('did-finish-load', async () => {
        try {
            await sleep(1);
            const hasApi = await browser.webContents.executeJavaScript('typeof AicuXHSApi !== "undefined"');
            console.log('[xhs-browser] Final check - Extension API available:', hasApi);
        } catch (err: any) {
            console.error('[xhs-browser] Failed to check extension:', err.message);
        }
    });

    browser.loadURL('https://www.xiaohongshu.com');

    // 监听验证码页面（仅在通过主窗口的"查看详情"按钮打开时才显示）
    browser.webContents.on('did-navigate', (event: any, url: string) => {
        // console.log('did-navigate-in-page:', url);
        // if (url.includes('/web-login/captcha')) {
        // 注释掉自动显示逻辑，因为主界面已经嵌入了登录界面
        // if (url && url.includes('/web-login/')) {
        //     browser.show();
        // }
    });

    return browser;
}


/**
 * 向小红书浏览器执行JS代码并获取结果
 * @param code js代码
 * @param tryCount 重试次数
 * @returns 执行结果
 */
const evalJs = async (code: string, tryCount: number = 0) => {
    if (tryCount > 3) {
        console.error('[evalJs] Max retries exceeded');
        return '执行失败！已重试3次！';
    }

    try {
        const browser = getBrowser();

        const web_href = await browser.webContents.executeJavaScript('location.href');
        console.log('[evalJs] Current URL:', web_href);

        if (web_href && web_href.includes('web-login/captcha')) {
            console.log('[evalJs] Captcha page detected, waiting...');
            await sleep(3);
            return evalJs(code, tryCount);
        }

        const result = await browser.webContents.executeJavaScript(code);
        console.log('[evalJs] Result:', JSON.stringify(result).substring(0, 100));

        // todo: 如果错误了（访问异常） 则自动弹出验证码页面。 同时进行等待循环直到成功（尝试3次）
        if (result && JSON.stringify(result).includes('访问频次异常')) {
            console.log('[evalJs] Rate limit detected, retrying...');
            await sleep(2 + tryCount);
            return evalJs(code, tryCount + 1);
        }
        return result;
    } catch (error: any) {
        console.error('[evalJs] Error executing script:', error.message);
        throw error;
    }
}

const httpGet = async (url: String) => {
    return await evalJs(`AicuXHSApi.get('${url}');`);
};
const httpPost = async (url: String, data: Object) => {
    return await evalJs(`AicuXHSApi.post('${url}', ${JSON.stringify(data)});`);
};

/**
 * 上传图片文件到小红书
 * @param filePath 本地文件路径
 * @returns file_id 或错误信息
 */
const uploadImage = async (filePath: string) => {
    try {
        // 读取文件并转换为 base64
        const fileBuffer = fs.readFileSync(filePath);
        const base64Data = fileBuffer.toString('base64');
        const fileName = path.basename(filePath);
        const fileSize = fileBuffer.length;

        console.log(`[uploadImage] 准备上传图片: ${fileName}, 大小: ${fileSize} bytes`);

        // 1. 获取上传许可
        const permitRes = await httpGet(
            'https://edith.xiaohongshu.com/api/media/v1/upload/web/permit?biz_name=spectrum&scene=image&file_count=1&version=1&source=web'
        );

        if (!permitRes.upload_id || !permitRes.file_ids || permitRes.file_ids.length === 0) {
            throw new Error('获取上传许可失败：' + JSON.stringify(permitRes));
        }

        const uploadId = permitRes.upload_id;
        const fileId = permitRes.file_ids[0];

        console.log(`[uploadImage] 获取到 upload_id: ${uploadId}, file_id: ${fileId}`);

        // 2. 上传图片数据（通过浏览器执行）
        const uploadCode = `
            (async () => {
                const base64Data = '${base64Data}';
                const blob = await (await fetch('data:image/jpeg;base64,' + base64Data)).blob();

                const formData = new FormData();
                formData.append('file', blob, '${fileName}');
                formData.append('upload_id', '${uploadId}');

                const response = await fetch('https://edith.xiaohongshu.com/api/media/v1/upload/web/file', {
                    method: 'POST',
                    body: formData,
                    credentials: 'include'
                });

                return await response.json();
            })();
        `;

        const uploadRes = await evalJs(uploadCode);
        console.log(`[uploadImage] 上传结果:`, JSON.stringify(uploadRes).substring(0, 200));

        if (uploadRes.success || uploadRes.file_id) {
            return {
                file_id: uploadRes.file_id || fileId,
                upload_id: uploadId,
                url: uploadRes.url
            };
        }

        throw new Error('图片上传失败：' + JSON.stringify(uploadRes));
    } catch (error: any) {
        console.error('[uploadImage] 上传失败:', error.message);
        throw error;
    }
};

/**
 * 发布笔记
 * @param noteData 笔记数据
 * @returns 发布结果
 */
const publishNote = async (noteData: {
    title: string;
    desc: string;
    type: string;
    file_ids?: string[];
    video_id?: string;
    topics?: string[];
    location?: string;
}) => {
    try {
        const postData: any = {
            title: noteData.title,
            desc: noteData.desc,
            etype: noteData.type,
            privacy_info: {
                type: 0 // 公开
            }
        };

        // 添加图片
        if (noteData.file_ids && noteData.file_ids.length > 0) {
            postData.image_info = {
                images: noteData.file_ids.map((id, index) => ({
                    file_id: id,
                    index: index
                }))
            };
        }

        // 添加视频
        if (noteData.video_id) {
            postData.video_info = {
                video_id: noteData.video_id
            };
        }

        // 添加话题
        if (noteData.topics && noteData.topics.length > 0) {
            postData.hash_tag = noteData.topics.map(t => ({ name: t }));
        }

        // 添加位置
        if (noteData.location) {
            postData.location = { name: noteData.location };
        }

        console.log('[publishNote] 准备发布笔记:', JSON.stringify(postData, null, 2));

        // 调用发布API
        const result = await httpPost('https://creator.xiaohongshu.com/api/v1/note/publish', postData);

        return result;
    } catch (error: any) {
        console.error('[publishNote] 发布失败:', error.message);
        throw error;
    }
};

let SAVE_DATA_PATH: string = '';
const setSaveDataPath = (p: string) => {
    console.log('[set save path]', p);
    SAVE_DATA_PATH = p;
}

// 内测
// TODO: 存储到文件，避免失效
const getJoinedTest = () => {
    // return store.get('isTest');
    const conf = loadConfig();
    return conf.isTest;
}
/**
 * 导出CSV数据
 * @param name 文件名
 * @param data 数据
 * @returns msg
 */
const downloadCsvData = (name: string, data: string) => {
    console.log('[download csv]', name, SAVE_DATA_PATH)
    if (!SAVE_DATA_PATH) return {
        error: '未设置数据存储目录'
    };
    const filePath = path.join(SAVE_DATA_PATH, name.endsWith('.csv') ? name : `${name}.csv`);
    fs.writeFileSync(filePath, data);
    return {
        error: '',
        link: filePath
    };
}

/**
 * 获取当前登陆账号信息｜游客
 * @returns 用户信息
 */
const getUserInfo = async () => {
    try {
        // 确保扩展已加载
        await ensureExtensionLoaded();

        // 等待一下让扩展有时间注入
        await sleep(1);

        // 先检查 AicuXHSApi 是否存在
        const hasApi = await evalJs(`typeof AicuXHSApi !== 'undefined'`);
        console.log('[getUserInfo] AicuXHSApi available:', hasApi);

        if (!hasApi) {
            console.log('[getUserInfo] AicuXHSApi not loaded, reloading page...');
            const browser = getBrowser();
            await browser.webContents.reload();
            await sleep(3); // 等待页面重新加载

            // 再次检查
            const hasApiAfterReload = await evalJs(`typeof AicuXHSApi !== 'undefined'`);
            if (!hasApiAfterReload) {
                console.error('[getUserInfo] Extension still not available after reload');
                return { guest: true };
            }
        }

        const userInfo = await evalJs(`AicuXHSApi.get('/api/sns/web/v2/user/me');`);
        return userInfo;
    } catch (error: any) {
        console.error('[getUserInfo] Error:', error.message);
        return { guest: true }; // 返回游客状态
    }
}

const sleep = async (tm = 1) => new Promise(RES => {
    setTimeout(RES, tm > 1000 ? tm : tm * 1000);
});

// json转换成csv
// ['note_id@id', 'note.title@title']..
const jsonToCsv = (jsonData: Array<any>, fields: Array<string>, arrayDelimiter: string = ";") => {
    // 检查输入数据是否有效
    if (!Array.isArray(jsonData) || !Array.isArray(fields) || fields.length === 0) {
        throw new Error("Invalid input data or fields");
    }

    // 解析字段并提取标题和路径
    const parsedFields = fields.map((field) => {
        const parts = field.split("@");
        if (parts.length === 2) {
            return { header: parts[0], path: parts[1] };
        } else {
            return { header: parts[0], path: parts[0] }; // 没有 @ 符号时，标题和路径相同
        }
    });

    // 生成 CSV 标题
    const csvHeaders = parsedFields.map(field => field.header).join(",");
    let csvContent = csvHeaders + "\n";

    // 遍历 JSON 数据
    jsonData.forEach((item) => {
        // 提取每个字段的值
        const row = parsedFields.map((field) => {
            // 按照点号分割字段路径
            const fieldParts = field.path.split(".");
            let value = item;

            // 逐级访问嵌套字段
            for (const part of fieldParts) {
                if (value && typeof value === "object" && part in value) {
                    value = value[part];
                } else {
                    value = ""; // 如果路径不存在，返回空字符串
                    break;
                }
            }

            // 处理数组类型的数据
            if (Array.isArray(value)) {
                // 将数组元素用指定的分隔符连接成字符串
                value = value.map(v => {
                    // 如果数组中的元素是对象或数组，转换为 JSON 字符串
                    return typeof v === "object" ? JSON.stringify(v) : v;
                }).join(arrayDelimiter);
            }

            // 如果值包含逗号、换行符或双引号，需要用双引号包裹
            if (typeof value === "string" && (value.includes(",") || value.includes("\n") || value.includes('"'))) {
                value = `"${value.replace(/"/g, '""')}"`; // 替换双引号为两个双引号以符合 CSV 规范
            }
            return value;
        });

        // 将当前行的值拼接为 CSV 格式
        csvContent += row.join(",") + "\n";
    });

    return csvContent;
}


export = { getBrowser, httpGet, httpPost, downloadCsvData, sleep, getUserInfo, setSaveDataPath, jsonToCsv, getJoinedTest, uploadImage, publishNote };
